﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CheccCoverplateCulvertAssemble.Operation.section
{
    internal class CastInPlaceSlabCulvertSubsection//现浇
    {
        /// <summary>
        /// 计算盖板涵分段数据
        /// </summary>
        /// <param name="slabCulvertLength">涵长</param>
        /// <param name="leftCustomizationLength">左侧定制</param>
        /// <param name="reightCustomizationLength">右侧定制</param>
        /// <param name="minLength">最小区间值</param>
        /// <param name="maxLenth">最大区间值</param>
        /// <param name="embeddedContinue">true为内嵌，false为外延</param>
        /// <param name="leftInline">进水口内嵌</param>
        public static (List<double> lengthOfPanelSubsection, List<double> SectionSubsection) GetslabCulvertSubsectionData(double slabCulvertLength, double leftCustomizationLength, double reightCustomizationLength, double minLength, double maxLenth,double leftInline, bool embeddedContinue, out double rightInlineExtension)//,double leftInline
        {
            //板长
            double lengthOfPanel = 2;
            //中间长度
            double centreLength = Convert.ToDouble(Convert.ToDecimal(slabCulvertLength) - Convert.ToDecimal(leftCustomizationLength) - Convert.ToDecimal(reightCustomizationLength) - Convert.ToDecimal(leftInline));
            if (centreLength != (int)centreLength)
            {
                if (embeddedContinue == true)
                {
                    rightInlineExtension = Convert.ToDouble(Convert.ToDecimal(centreLength) - Convert.ToDecimal(Convert.ToDouble(centreLength.ToString("f1"))));
                    centreLength = Convert.ToDouble(centreLength.ToString("f1"));
                }
                else
                {
                    rightInlineExtension = Convert.ToDouble(Convert.ToDecimal(Convert.ToDouble(centreLength.ToString("f1"))) + Convert.ToDecimal(0.1) - Convert.ToDecimal(centreLength));
                    centreLength = Convert.ToDouble(Convert.ToDecimal(Convert.ToDouble(centreLength.ToString("f1"))) + Convert.ToDecimal(0.1));
                }                  
            }
            else
                rightInlineExtension = 0;
            //板长分段数据
            List<double> lengthOfPanelSubsection = new List<double>();
            lengthOfPanelSubsection.Add(leftCustomizationLength);
            List<double> centreData = GetLengthOfPanelSubsection(centreLength, lengthOfPanel);
            lengthOfPanelSubsection.AddRange(centreData);
            lengthOfPanelSubsection.Add(reightCustomizationLength);
            //区间分段数据
            if (leftCustomizationLength < minLength)
            {
                for (int i = 0; i < centreData.Count; i++)
                {
                    leftCustomizationLength += centreData[i];
                    centreData.RemoveAt(i);
                    i--;
                    if (leftCustomizationLength >= minLength && leftCustomizationLength <= maxLenth)
                        break;
                }
            }
            if (reightCustomizationLength < minLength)
            {
                for (int i = centreData.Count - 1; i >= 0; i--)
                {
                    reightCustomizationLength += centreData[i];
                    centreData.RemoveAt(i);
                    if (reightCustomizationLength >= minLength && reightCustomizationLength <= maxLenth)
                        break;
                }
            }
            centreLength = centreData.Sum();
            List<double> SectionSubsection = new List<double>();
            //SectionSubsection.Add(leftCustomizationLength);
           // if (centreLength >= 2 * minLength)
                SectionSubsection.AddRange(Calc(lengthOfPanelSubsection, maxLenth, minLength, lengthOfPanel).ToList());
           // else
             //   SectionSubsection.Add(centreLength);
            //SectionSubsection.Add(reightCustomizationLength);
            return (lengthOfPanelSubsection, SectionSubsection);
        }
        /// <summary>
        /// 板长分段
        /// </summary>
        /// <param name="centreLength">涵长中间长度</param>
        /// <param name="lengthOfPanel">板长</param>
        public static List<double> GetLengthOfPanelSubsection(double centreLength,double lengthOfPanel)
        {
            double precision = 0.1;
            List<double> LengthOfPanelSubsectionList = new List<double>();
            //计算有多少个板长
            double count = (int)(centreLength / 2);
            //剩余长度
            double residueLength = Convert.ToDouble((Convert.ToDecimal(centreLength) - Convert.ToDecimal(count * 2)) / Convert.ToDecimal(2));
            for (int i = 0; i < count; i++)
            {
                if (i == 0)
                {
                    if (residueLength.ToString().Length > 3)
                        LengthOfPanelSubsectionList.Add(lengthOfPanel + Math.Floor(residueLength * 10) / 10);
                    else
                        LengthOfPanelSubsectionList.Add(lengthOfPanel + residueLength);
                }
                else if (i == count - 1)
                {
                    if (residueLength.ToString().Length > 3)
                        LengthOfPanelSubsectionList.Add(Convert.ToDouble( Convert.ToDecimal (lengthOfPanel) + Convert.ToDecimal(Math.Floor(residueLength * 10) / 10) + Convert.ToDecimal(precision)));
                    else
                        LengthOfPanelSubsectionList.Add(lengthOfPanel + residueLength);
                }  
                else
                    LengthOfPanelSubsectionList.Add(lengthOfPanel);
            }
            return LengthOfPanelSubsectionList;
        }

        //计算区间内标准值的最佳倍数值
        public static double GetSectionMinimumValue(double standard, double MinLength, double MaxLength)
        {
            double i = 1;
            double value = 0;
            while (true)
            {
                value = standard * i;
                if (value >= MinLength && value <= MaxLength)
                    return value;
                i++;
            }
        }
        //区间分段
        public static List<double> Calc(List<double> doubles, double MaxLength, double MinLength, double componentLength)
        {
            List<double> doubles1 = new List<double>();

            List<double> result = new List<double>(doubles);
            double math = 0;
              
            for (int i = 0; i < doubles.Count; i++)
            {
                result.RemoveAt(0);
                math += doubles[i];
                if (i == doubles.Count - 1)
                    doubles1.Add(math);
                else if (math >= MinLength && math <= MaxLength)
                {
                    doubles1.Add(math);
                    math = 0;
                    break;
                }
            }

            List<double> doubles2 = new List<double>(result);
            math = 0;
            for (int i = result.Count-1; i >=0; i--)
            {
                doubles2.RemoveAt(doubles2.Count - 1);
                math += result[i];
                if (i == 0)
                    doubles1.Add(math);
                else if (math >= MinLength && math <= MaxLength)
                {
                    doubles1.Add(math);
                    math = 0;
                    break;
                }
            }
            if (doubles2.Sum() < MinLength)
            {

                double mathSum = doubles2.Sum();
                for (int i = doubles1.Count-1; i >=0; i--)
                {
                    double s = doubles1[i];
                    for (double j = 1; j <= mathSum; j+= componentLength)
                    {
                        if(s+ componentLength>= MinLength&& s + componentLength <= MaxLength)
                        {
                            s += componentLength;
                        }
                    }
                    mathSum = mathSum-( s - doubles1[i]);
                    doubles1[i] = s;
                }
                if (mathSum != 0)
                    doubles1.Add(mathSum);

            }
            else
            {
                doubles2 = CalMath(doubles2.Sum(), MaxLength, MinLength, componentLength).ToList();
                math = 0;
                for (int i = 0; i < doubles2.Count; i++)
                {
                    doubles1.Insert(doubles1.Count - 1, doubles2[i]);
                }
            }

            
            return doubles1;
        }




        public static double[] CalMath( double OverallLength, double MaxLength, double MinLength, double componentLength)
        {
            double[] Segment = null;
            try
            {
                //区间内标准值的最佳倍数值
                MinLength = GetSectionMinimumValue(componentLength, MinLength, MaxLength);

                int num = (int)(OverallLength / MinLength);
                var remainder = OverallLength % MinLength;
                Segment = new double[num];
                for (int i = 0; i < num; i++)
                {
                    Segment[i] = MinLength;
                }

                bool flag = false;

                while (remainder > 0&& num>0)
                {
                    for (int i = 0; i < num; i++)
                    {
                        var length = Segment.Length - 1 - i;
                        if (Segment[length] >= MaxLength)
                        {
                            flag = true;
                            break;
                        }
                        if (remainder >= componentLength)
                        {
                            Segment[length] += componentLength;
                            remainder -= componentLength;
                        }
                        else
                        {
                            Segment[length] += remainder;
                            remainder -= remainder;
                        }
                        if (remainder == 0)
                        {
                            flag = true;
                            break;
                        }
                    }
                    if (flag == true)
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return Segment;
        }
    }
}
